﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using Microsoft.Win32;
using System.Runtime.Serialization.Formatters.Binary;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Windows.Media.Imaging;

using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Navigation;
using System.Collections.Specialized;
using System.Runtime.Serialization;
using System.Runtime.InteropServices;


namespace pGrid
{
  [Serializable]
  class Game
  {
    private int m_currentAuctionPlayer;
    private int m_round;
    private int m_currentGamePhase; // Фаза. 1,2,3
    private int m_currentGameStage; // Этап. 1,2,3,4,5
    private int PLAYER_HAS_STATIONS;
    private int REMOVE_STATIONS;
    private int GAME_ZONES;
    private int CITY_IN_REGION_NUM;
    private int MAX_CITY_NUM;
    private int PLAYERS_NUMBER;
    
    private BitmapImage m_socket_pic;
    private Player m_currentPlayer = new Player();
    private PowerStation m_currentStation = new PowerStation();

    private ResourceManager m_resManager = new ResourceManager();
    private AuctionManager m_auctionManager = new AuctionManager();
    private StationManager m_stationManager = new StationManager();
    

    private ObservableCollection<Player> m_playerList = new ObservableCollection<Player>();
    //private StationManager m_stationsExpected = new StationManager();

    public Game()
    {
      this.m_round = 0;
      this.m_currentGameStage = 0;
      this.m_currentGamePhase = -1;
    }
    public void SetGameParams(int count)
    {
      this.PLAYERS_NUMBER = count;
      InitGameConstants();
      m_stationManager.InitStations(REMOVE_STATIONS);
      InitPlayers();

      
      string path = "100.jpg";
      Stream stream = File.Open(path, FileMode.Open);
      this.m_socket_pic = new BitmapImage();
      this.m_socket_pic.BeginInit();
      this.m_socket_pic.StreamSource = stream;
      this.m_socket_pic.EndInit();
    }

    public IList<Player> PlayerList
    {
      get
      {
        return this.m_playerList;
      }
      set
      {
        this.m_playerList = (ObservableCollection<Player>)value;
      }
    }

    public StationManager StationManager
    {
      get
      {
        return this.m_stationManager;
      }
      set
      {
        this.m_stationManager = value;
      }
    }
    public void Add(Player item)
    {
      this.m_playerList.Add(item);
    }
    public override string ToString()
    {
      string temp = "";
      foreach (Player pl in m_playerList)
        temp += pl.ToString() + "\n";
      return temp;
    }
    

    //////////////////////////////////////////////////////////////////////////
    // Функции управления игрой                                             //
    //////////////////////////////////////////////////////////////////////////

    // Процесс игры
    public void ProceedGame()
    {
      UpdatePhase();
    }

    // Смена фазы игры
    public void UpdateStage()
    {
      switch (this.m_currentGameStage)
      {
        case 0: // Начало игры. Фаза 1.
        {

          break;
        }
        case 1: // Переход к фазе 2.
        {

          break;
        }
        case 2: // Переход к фазе 3.
        {
          break;
        }
      }
      this.m_currentGameStage++;
    }

    // Смена этапа игры
    public void UpdatePhase()
    {
      this.m_currentGamePhase = (this.m_currentGamePhase+1)%4; 
      
      switch (this.m_currentGamePhase)
      {
        case 0: // Аукцион электростанций. Этап 2.
        {
          GetPriorities(); // Определение очередности. Этап 1.
          PrepareAuction();
          //Auction();
          break;
        }
        case 1: // Покупка ресурсов. Этап 3.
        {
          break;
        }
        case 2: // Строительство. Этап 4.
        {
          break;
        }
        case 3: // Электрификация. Этап 5.
        {

          this.m_round++;
          break;
        }
      }
    }

    // Подготовка игроков к аукциону
    public void PrepareAuction()
    {
      foreach (Player p in this.m_playerList)
      {
        p.BuyStation = true;
      }
    }

    // Определение очередночти игроков
    public void GetPriorities()
    {

    }

    public int Round
    {
      get
      {
        return this.m_round;
      }
      set
      {
        this.m_round = value;
      }
    }

    public int CurrentAuctionPlayer
    {
      get
      {
        return this.m_currentAuctionPlayer;
      }
      set
      {
        this.m_currentAuctionPlayer = value;
      }
    }

    public int Phase
    {
      get
      {
        return this.m_currentGamePhase;
      }
      set
      {
        this.m_currentGamePhase = value;
      }
    }

    public int Stage
    {
      get
      {
        return this.m_currentGameStage;
      }
      set
      {
        this.m_currentGameStage = value;
      }
    }

    public Player CurrentPlayer
    {
      get
      {
        return this.m_currentPlayer;
      }
      set
      {
        this.m_currentPlayer = value;
      }
    }

    public PowerStation CurrentStation
    {
      get
      {
        return this.m_currentStation;
      }
      set
      {
        this.m_currentStation = value;
      }
    }

    public ResourceManager ResManager
    {
      get
      {
        return this.m_resManager;
      }
      set
      {
        this.m_resManager = value;
      }
    }

    public AuctionManager AuctionManager
    {
      get
      {
        return this.m_auctionManager;
      }
      set
      {
        this.m_auctionManager = value;
      }
    }

    public BitmapImage SocketPic
    {
      get
      {
        return this.m_socket_pic;
      }
      set 
      {
        this.m_socket_pic = value;
      }
    }

    // инициализация игроков
    void InitPlayers()
    {
      m_playerList.Add(new Player(Colors.red, 0, "Lovens"));
     // m_playerList[0].Station1 = m_stationManager.GetNewStationFromStock(0);
     // m_playerList[0].Station2 = m_stationManager.GetNewStationFromStock(1);
     // m_playerList[0].Station3 = m_stationManager.GetNewStationFromStock(2);
     // m_playerList[0].StationsNum = 3;
     // m_playerList[0].CitiesNum = 7;
      m_playerList.Add(new Player(Colors.purple, 1, "Pillar"));
      /*m_playerList[1].Station1 = m_stationManager.GetStation(3);
      m_playerList[1].Station2 = m_stationManager.GetStation(4);
      m_playerList[1].Station3 = m_stationManager.GetStation(5);
      m_playerList[1].StationsNum = 3;
      m_playerList[1].CitiesNum = 9;*/
      m_playerList.Add(new Player(Colors.yellow, 2, "Aska"));
     /* m_playerList[2].Station1 = m_stationManager.GetStation(6);
      m_playerList[2].Station2 = m_stationManager.GetStation(7);
      m_playerList[2].Station3 = m_stationManager.GetStation(8);
      m_playerList[2].StationsNum = 3;
      m_playerList[2].CitiesNum = 4;*/
      //newGame.Add(new Player(Colors.green, 4, "Zuz"));
      //newGame.Add(new Player(Colors.blue, 5, "Kot"));
      //newGame.Add(new Player(Colors.black, 6, "Koshka"));
    }
    //
    void InitGameConstants()
    {
      switch (this.PLAYERS_NUMBER)
      {
        #region two_players
        case 2:
          {
            PLAYER_HAS_STATIONS = 4;
            REMOVE_STATIONS = 8;
            GAME_ZONES = 3;
            CITY_IN_REGION_NUM = 10;
            MAX_CITY_NUM = 21;

            m_resManager.RESTORE_COAL1 = 3;
            m_resManager.RESTORE_OIL1 = 2;
            m_resManager.RESTORE_WASTE1 = 1;
            m_resManager.RESTORE_URANIUM1 = 1;

            m_resManager.RESTORE_COAL2 = 4;
            m_resManager.RESTORE_OIL2 = 2;
            m_resManager.RESTORE_WASTE2 = 2;
            m_resManager.RESTORE_URANIUM2 = 1;

            m_resManager.RESTORE_COAL3 = 3;
            m_resManager.RESTORE_OIL3 = 4;
            m_resManager.RESTORE_WASTE3 = 3;
            m_resManager.RESTORE_URANIUM3 = 1;
            break;
          }
        #endregion
        #region three_players
        case 3:
          {
            PLAYER_HAS_STATIONS = 3;
            REMOVE_STATIONS = 8;
            GAME_ZONES = 3;
            CITY_IN_REGION_NUM = 7;
            MAX_CITY_NUM = 17;

            m_resManager.RESTORE_COAL1 = 4;
            m_resManager.RESTORE_OIL1 = 2;
            m_resManager.RESTORE_WASTE1 = 1;
            m_resManager.RESTORE_URANIUM1 = 1;

            m_resManager.RESTORE_COAL2 = 5;
            m_resManager.RESTORE_OIL2 = 3;
            m_resManager.RESTORE_WASTE2 = 2;
            m_resManager.RESTORE_URANIUM2 = 1;

            m_resManager.RESTORE_COAL3 = 3;
            m_resManager.RESTORE_OIL3 = 4;
            m_resManager.RESTORE_WASTE3 = 3;
            m_resManager.RESTORE_URANIUM3 = 1;
            break;
          }
        #endregion
        #region four_players
        case 4:
          {
            PLAYER_HAS_STATIONS = 3;
            REMOVE_STATIONS = 4;
            GAME_ZONES = 4;
            CITY_IN_REGION_NUM = 7;
            MAX_CITY_NUM = 17;

            m_resManager.RESTORE_COAL1 = 5;
            m_resManager.RESTORE_OIL1 = 3;
            m_resManager.RESTORE_WASTE1 = 2;
            m_resManager.RESTORE_URANIUM1 = 1;

            m_resManager.RESTORE_COAL2 = 6;
            m_resManager.RESTORE_OIL2 = 4;
            m_resManager.RESTORE_WASTE2 = 3;
            m_resManager.RESTORE_URANIUM2 = 2;

            m_resManager.RESTORE_COAL3 = 4;
            m_resManager.RESTORE_OIL3 = 5;
            m_resManager.RESTORE_WASTE3 = 4;
            m_resManager.RESTORE_URANIUM3 = 2;
            break;
          }
        #endregion
        #region five_players
        case 5:
          {
            PLAYER_HAS_STATIONS = 3;
            REMOVE_STATIONS = 0;
            GAME_ZONES = 5;
            CITY_IN_REGION_NUM = 7;
            MAX_CITY_NUM = 15;

            m_resManager.RESTORE_COAL1 = 5;
            m_resManager.RESTORE_OIL1 = 4;
            m_resManager.RESTORE_WASTE1 = 3;
            m_resManager.RESTORE_URANIUM1 = 2;

            m_resManager.RESTORE_COAL2 = 7;
            m_resManager.RESTORE_OIL2 = 5;
            m_resManager.RESTORE_WASTE2 = 3;
            m_resManager.RESTORE_URANIUM2 = 3;

            m_resManager.RESTORE_COAL3 = 5;
            m_resManager.RESTORE_OIL3 = 6;
            m_resManager.RESTORE_WASTE3 = 5;
            m_resManager.RESTORE_URANIUM3 = 2;
            break;
          }
        #endregion
        #region six_players
        case 6:
          {
            PLAYER_HAS_STATIONS = 3;
            REMOVE_STATIONS = 0;
            GAME_ZONES = 5;
            CITY_IN_REGION_NUM = 6;
            MAX_CITY_NUM = 14;

            m_resManager.RESTORE_COAL1 = 7;
            m_resManager.RESTORE_OIL1 = 5;
            m_resManager.RESTORE_WASTE1 = 3;
            m_resManager.RESTORE_URANIUM1 = 2;

            m_resManager.RESTORE_COAL2 = 9;
            m_resManager.RESTORE_OIL2 = 6;
            m_resManager.RESTORE_WASTE2 = 5;
            m_resManager.RESTORE_URANIUM2 = 3;

            m_resManager.RESTORE_COAL3 = 6;
            m_resManager.RESTORE_OIL3 = 7;
            m_resManager.RESTORE_WASTE3 = 6;
            m_resManager.RESTORE_URANIUM3 = 3;
            break;
          }
        #endregion
      }
    }
/*
    public void Stage1()
    {

    }
    public void Stage2()
    {

    }
    public void Stage3()
    {

    }
    */

    public Player GetByRating(int rating)
    {
      for (int i = 0; i < this.m_playerList.Count; i++)
      {
        if (this.m_playerList[i].Rating == rating)
          return this.m_playerList[i];
      }
      return null;
    }



    //---------------------------------------OTHER FUNCTIONS---------------------------------------------------------
    // предполагается, что эти функции вызываются когда игрок еще может положить ресурсы на склады станций
    public void BuyCoal(int price)
    {
      if (!m_currentPlayer.TryPutResourseOnStation(m_currentPlayer.Station1, ResourseType.coal))
        if (!m_currentPlayer.TryPutResourseOnStation(m_currentPlayer.Station2, ResourseType.coal))
          if (!m_currentPlayer.TryPutResourseOnStation(m_currentPlayer.Station3, ResourseType.coal))
            m_currentPlayer.TryPutResourseOnStation(m_currentPlayer.Station4, ResourseType.coal);
      m_currentPlayer.CoalNum++;
      m_currentPlayer.Money -= price;
    }
    public void BuyOil(int price)
    {
      if (!m_currentPlayer.TryPutResourseOnStation(m_currentPlayer.Station1, ResourseType.oil))
        if (!m_currentPlayer.TryPutResourseOnStation(m_currentPlayer.Station2, ResourseType.oil))
          if (!m_currentPlayer.TryPutResourseOnStation(m_currentPlayer.Station3, ResourseType.oil))
            m_currentPlayer.TryPutResourseOnStation(m_currentPlayer.Station4, ResourseType.oil);
      m_currentPlayer.OilNum++;
      m_currentPlayer.Money -= price;
    }
    public void BuyWaste(int price)
    {
      if (!m_currentPlayer.TryPutResourseOnStation(m_currentPlayer.Station1, ResourseType.waste))
        if (!m_currentPlayer.TryPutResourseOnStation(m_currentPlayer.Station2, ResourseType.waste))
          if (!m_currentPlayer.TryPutResourseOnStation(m_currentPlayer.Station3, ResourseType.waste))
            m_currentPlayer.TryPutResourseOnStation(m_currentPlayer.Station4, ResourseType.waste);
      m_currentPlayer.WasteNum++;
      m_currentPlayer.Money -= price;
    }
    public void BuyUranium(int price)
    {
      if (!m_currentPlayer.TryPutResourseOnStation(m_currentPlayer.Station1, ResourseType.uranium))
        if (!m_currentPlayer.TryPutResourseOnStation(m_currentPlayer.Station2, ResourseType.uranium))
          if (!m_currentPlayer.TryPutResourseOnStation(m_currentPlayer.Station3, ResourseType.uranium))
            m_currentPlayer.TryPutResourseOnStation(m_currentPlayer.Station4, ResourseType.uranium);
      m_currentPlayer.UraniumNum++;
      m_currentPlayer.Money -= price;
    }

    public void BuyStationReplace(int num_deleted_station, int num_bought_station)
    {
      PowerStation delSt = new PowerStation();
      switch (num_deleted_station)
      {
        case 1: { delSt = m_currentPlayer.Station1; break; }
        case 2: { delSt = m_currentPlayer.Station2; break; }
        case 3: { delSt = m_currentPlayer.Station3; break; }
        case 4: { delSt = m_currentPlayer.Station4; break; }
      }
      PowerStation newSt = new PowerStation();
      switch (num_bought_station)
      {
        case 1: { newSt = m_stationManager.StationsExpected.ElementAt(0).Value; break; }
        case 2: { newSt = m_stationManager.StationsExpected.ElementAt(1).Value; break; }
        case 3: { newSt = m_stationManager.StationsExpected.ElementAt(2).Value; break; }
        case 4: { newSt = m_stationManager.StationsExpected.ElementAt(3).Value; break; }
      }
      m_currentPlayer.DeleteStation(delSt.Number);
     // m_currentPlayer.StationsNum++;
      m_currentPlayer.Money -= newSt.Cost;
      m_currentPlayer.TryBuyStation(newSt);
      m_stationManager.UpdateExpected(newSt);
    }

    public void BuyStation(int num_bought_station) // num_bought_station - номер нажатой картинки в верхней панели, 
    {
      PowerStation tmpSt = new PowerStation();
      switch (num_bought_station)
      {
        case 1: { tmpSt = m_stationManager.StationsExpected.ElementAt(0).Value; break; }
        case 2: { tmpSt = m_stationManager.StationsExpected.ElementAt(1).Value; break; }
        case 3: { tmpSt = m_stationManager.StationsExpected.ElementAt(2).Value; break; }
        case 4: { tmpSt = m_stationManager.StationsExpected.ElementAt(3).Value; break; }
      }
      m_currentPlayer.Money -= tmpSt.Cost;
      m_currentPlayer.TryBuyStation(tmpSt);
      m_stationManager.UpdateExpected(tmpSt);
    }
    
  }
}
